package com.groupbuying.provider.service.impl;

import com.groupbuying.provider.connector.FileFegin;
import com.groupbuying.provider.dao.StoreShopDao;
import com.groupbuying.provider.domain.StoreShopDO;
import com.groupbuying.provider.dto.*;
import com.groupbuying.provider.dto.app.StoreShopAppDTO;
import com.groupbuying.provider.dto.app.StoreShopAppPageDTO;
import com.groupbuying.provider.dto.convert.StoreShopConvert;
import com.groupbuying.provider.service.StoreShopAppService;
import com.groupbuying.provider.utils.DistanceUtils;
import com.groupbuying.provider.utils.GeoHashUtils;
import com.groupbuying.provider.utils.RedisUtils;
import com.groupbuying.provider.utils.apiresult.ApiResult;
import com.groupbuying.provider.utils.apiresult.AppApiResult;
import com.groupbuying.provider.utils.apiresult.JsonUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @Author: wenguoqiang
 * @Email wguoqiango@163.com
 * @Date: 2020/1/7 0007 上午 10:21
 * @Des
 */
@Service
public class StoreShopAppServiceImpl implements StoreShopAppService {


    @Autowired
    private StoreShopDao storeShopDao;
    @Autowired
    private FileFegin fileFegin;
    @Autowired
    private RedisUtils redisUtils;


    private final String NEARLIST_POSTFIX = "nearbyList";
    private final String LGTLAT_POSTFIX = "lgtlat";


    public ApiResult getShopList(Map<String, Object> params) {
        Object temp = params.get("longitude");
        Double longitude = temp != null ? new BigDecimal(temp.toString()).doubleValue() : null;
        //纬度
        temp = params.get("latitude");
        Double latitude = temp != null ? new BigDecimal(temp.toString()).doubleValue() : null;
        // 每页显示的条数
        temp = params.get("pageShow");
        Integer pageShow = temp != null ? Integer.parseInt(temp.toString()) : null;
        // 页码
        temp = params.get("page");
        Integer page = temp != null ? Integer.parseInt(temp.toString()) : null;

        temp = params.get("level");
        Integer level = temp != null ? Integer.parseInt(temp.toString()) : null;

        temp = params.get("customerUuid");
        String customerUuid = temp != null ? temp.toString() : null;

        if (longitude == null || latitude == null
                || pageShow == null || pageShow == 0
                || level == null || page == null || page == 0) {
            return AppApiResult.failure("params is null");
        }


        //获取
        String geoCode = GeoHashUtils.getGeoHash(latitude, longitude, level);
        String[] geoCodes = GeoHashUtils.getAdjacent(latitude, longitude, level);
        Map<String, Object> map = new HashMap<>();
        for (int i = 0; i < geoCodes.length; i++) {
            map.put("geoCode" + (i + 1), geoCodes[i]);
        }
        map.put("geoCode9", geoCode);
        map.put("level", level);

        long startTime = System.currentTimeMillis();
        List<StoreShopDO> queryList = storeShopDao.queryListByGeoHashInApp(map);
        long endTime = System.currentTimeMillis();
        System.out.println("查询时间："+(endTime - startTime));

        startTime = endTime ;
        if (!(queryList.size() > 0)) {
            return AppApiResult.success(new StoreShopPageDTO(0, 0, pageShow, new ArrayList<>()));
        }

        //保存距离 修改图片地址
        List<StoreShopAppDTO> shopList = new ArrayList<>();

        dealStoreData(longitude, latitude, queryList, shopList);
        endTime = System.currentTimeMillis();
        System.out.println("整理加排序时间："+(endTime - startTime));

        //获取页码数据
        return AppApiResult.success(getPagedListbyPage(shopList, pageShow, page));
    }

    private void cacheLgtLat(Double longitude, Double latitude, String customerLgtLatKey) {
        Map redisData = new HashMap();
        redisData.put("longitude", longitude);
        redisData.put("latitude", latitude);
        redisUtils.setKey(customerLgtLatKey, JsonUtils.toJSon(redisData),86400);
    }


    private  List<StoreShopAppDTO> cacaheStore(String customerUuid, List<StoreShopAppDTO> shopList) {

        int shopListSize = shopList.size();
        List nearbyList = shopList.subList(0, shopListSize > 21 ? 21 : shopListSize);
        redisUtils.setKey(customerUuid + NEARLIST_POSTFIX, JsonUtils.toJSon(nearbyList),86400);
        return nearbyList;
    }

    @Override
    public ApiResult searchShopListByCategoryOrStoreName(Map<String, Object> params) {
        //经度
        Object temp = params.get("longitude");
        Double longitude = temp != null ? new BigDecimal(temp.toString()).doubleValue() : null;
        //纬度
        temp = params.get("latitude");
        Double latitude = temp != null ? new BigDecimal(temp.toString()).doubleValue() : null;
        // 每页显示的条数
        temp = params.get("pageShow");
        Integer pageShow = temp != null ? Integer.parseInt(temp.toString()) : null;
        // 页码
        temp = params.get("page");
        Integer page = temp != null ? Integer.parseInt(temp.toString()) : null;
        // 品类名称
        temp = params.get("categoryName");
        String categoryName = temp != null ? temp.toString() : null;
        // 部分品类名称 用于模糊匹配
        temp = params.get("categoryNamePart");
        String categoryNamePart = temp != null ? temp.toString() : null;
        // 商户名称
        temp = params.get("storeName");
        String storeName = temp != null ? temp.toString() : null;
        // 商户名称
        temp = params.get("storeNameOrCategoryNamePart");
        String storeNameOrCategoryNamePart = temp != null ? temp.toString() : null;
        //会员uuid
        temp = params.get("customerUuid");
        String customerUuid = temp != null ? temp.toString() : null;


        if (pageShow == null || pageShow == 0 || page == null || page == 0) {
            return AppApiResult.failure("params is null");
        }

        //获取
        Map map = new HashMap();
        map.put("categoryName", categoryName);
        map.put("storeName", storeName);
        map.put("categoryNamePart", categoryNamePart);
        map.put("storeNameOrCategoryNamePart", storeNameOrCategoryNamePart);
        //获取商家数据
        List<StoreShopDO> queryList = storeShopDao.searchShopListByCategoryOrStoreName(map);

        if (!(queryList.size() > 0)) {
            return AppApiResult.success(new StoreShopPageDTO(0, 0, pageShow, new ArrayList<>()));
        }

        //保存距离 修改图片地址
        List<StoreShopAppDTO> shopList = new ArrayList<>();
        dealStoreData(longitude, latitude, queryList, shopList);
        //获取页码数据
        return AppApiResult.success(getPagedListbyPage(shopList, pageShow, page));
    }

    @Override
    public ApiResult getRecommendNearbyStoreList(Map<String, Object> params) {
        //经度
        Object temp = params.get("longitude");
        Double longitude = temp != null ? new BigDecimal(temp.toString()).doubleValue() : null;
        //纬度
        temp = params.get("latitude");
        Double latitude = temp != null ? new BigDecimal(temp.toString()).doubleValue() : null;
        //会员uuid
        temp = params.get("customerUuid");
        String customerUuid = temp != null ? temp.toString() : null;
        //商户uuid
        temp = params.get("storeUuid");
        String storeUuid = temp != null ? temp.toString() : null;
        //查找范围
        temp = params.get("level");
        Integer level = temp != null ? Integer.parseInt(temp.toString()) : null;


        if (latitude == null || latitude == 0 || longitude == null || longitude == 0 || level == null|| StringUtils.isBlank(customerUuid) || StringUtils.isBlank(storeUuid)) {
            return AppApiResult.failure("params is null");
        }

        String customerLgtLatKey = customerUuid+LGTLAT_POSTFIX;
        Object lgtLatObj = redisUtils.getValue(customerLgtLatKey);
        String lgtLat = lgtLatObj == null ? null : lgtLatObj.toString();
        if (StringUtils.isNotBlank(lgtLat)) {

            Map lgtLatMap = JsonUtils.convertBean(lgtLat, HashMap.class);
            double distance = DistanceUtils.getDistance(longitude, latitude, new BigDecimal(lgtLatMap.get("longitude").toString()).doubleValue(), new BigDecimal(lgtLatMap.get("latitude").toString()).doubleValue());
            if (new BigDecimal(distance).compareTo(new BigDecimal(50)) == 1) {
                //查库获取
                return AppApiResult.success(getNearbyStorePageDTO(storeUuid,  getNearbyListbyDB(longitude, latitude, customerUuid,level,customerLgtLatKey)));
            }
            //缓存处理
            return AppApiResult.success(getCacheNearbyPageDTO(customerUuid, storeUuid));
        }else{
            //查库处理
            return AppApiResult.success(getNearbyStorePageDTO(storeUuid,  getNearbyListbyDB(longitude, latitude, customerUuid,level,customerLgtLatKey)));

        }

    }

    private StoreShopAppPageDTO getCacheNearbyPageDTO(String customerUuid, String storeUuid) {
        Object nearlistObj = redisUtils.getValue(customerUuid + NEARLIST_POSTFIX);
        String shopListStr = nearlistObj == null ? null : nearlistObj.toString();
        if (StringUtils.isBlank(shopListStr)) {
            return new StoreShopAppPageDTO(0,1,20,new ArrayList<>());
        }
        List<StoreShopAppDTO> redisShopList = JsonUtils.convertBean(shopListStr, ArrayList.class,StoreShopAppDTO.class);

        if (!(redisShopList.size() > 0)) {
            return new StoreShopAppPageDTO(0,1,20,new ArrayList<>());
        }

        return getNearbyStorePageDTO(storeUuid, redisShopList);

    }

    private List<StoreShopAppDTO> getNearbyListbyDB(Double longitude, Double latitude, String customerUuid ,Integer level,String customerLgtLatKey) {
        String geoCode = GeoHashUtils.getGeoHash(latitude, longitude, level);
        String[] geoCodes = GeoHashUtils.getAdjacent(latitude, longitude, level);
        Map<String, Object> map = new HashMap<>();
        for (int i = 0; i < geoCodes.length; i++) {
            map.put("geoCode" + (i + 1), geoCodes[i]);
        }
        map.put("geoCode9", geoCode);
        map.put("level", level);

        List<StoreShopDO> queryList = storeShopDao.queryListByGeoHashInApp(map);

        if (!(queryList.size() > 0)) {
            return new ArrayList<>();
        }

        //保存距离 修改图片地址
        List<StoreShopAppDTO> shopList = new ArrayList<>();
        dealStoreData(longitude, latitude, queryList, shopList);
        //放入缓存
        shopList = cacaheStore(customerUuid, shopList);
        cacheLgtLat(longitude,latitude,customerLgtLatKey);
        return shopList;
    }

    private StoreShopAppPageDTO getNearbyStorePageDTO(String storeUuid, List<StoreShopAppDTO> shopList) {
        List<StoreShopAppDTO> recommendNearbyStoreList = new ArrayList<>();
        if(!(shopList.size()>0)){
            return new StoreShopAppPageDTO(recommendNearbyStoreList.size(),1,20, recommendNearbyStoreList);
        }
        for (StoreShopAppDTO shop : shopList) {
            if (shop.getShop().getStoreUuid().equals(storeUuid) || recommendNearbyStoreList.size() == 20) {
                continue;
            }
            recommendNearbyStoreList.add(shop);
        }
        return new StoreShopAppPageDTO(recommendNearbyStoreList.size(),1,20, recommendNearbyStoreList);
    }

    public void dealStoreData(Double longitude, Double latitude, List<StoreShopDO> storeShopList, List<StoreShopAppDTO> shopList) {
        if (longitude == null || latitude == null) {
            for (StoreShopDO storeShop : storeShopList) {

                StorePhotoDTO storePhotoDTO = new StorePhotoDTO();
                storePhotoDTO.setSlideshow(fileFegin.getDownloadUrlByFileGroupKey(storeShop.getSlideshow()));
                storePhotoDTO.setDoorPhoto(fileFegin.getDownloadUrlByFileGroupKey(storeShop.getDoorphoto()));
                storePhotoDTO.setWithinPhoto(fileFegin.getDownloadUrlByFileGroupKey(storeShop.getWithinphoto()));
                StoreShopAppDTO storeShopAppDTO = new StoreShopAppDTO();
                storeShopAppDTO.setShop(StoreShopConvert.MAPPER.doToDTO(storeShop));
                storeShopAppDTO.setDistance("distance is null");
                storeShopAppDTO.setPhoto(storePhotoDTO);
                storeShopAppDTO.setScore("5");
                shopList.add(storeShopAppDTO);
            }
        } else {
            for (StoreShopDO storeShop : storeShopList) {

                StorePhotoDTO storePhotoDTO = new StorePhotoDTO();
                storePhotoDTO.setSlideshow(fileFegin.getDownloadUrlByFileGroupKey(storeShop.getSlideshow()));
                storePhotoDTO.setDoorPhoto(fileFegin.getDownloadUrlByFileGroupKey(storeShop.getDoorphoto()));
                storePhotoDTO.setWithinPhoto(fileFegin.getDownloadUrlByFileGroupKey(storeShop.getWithinphoto()));
                StoreShopAppDTO storeShopAppDTO = new StoreShopAppDTO();
                storeShopAppDTO.setShop(StoreShopConvert.MAPPER.doToDTO(storeShop));
                storeShopAppDTO.setDistance(DistanceUtils.getDistance(longitude, latitude, storeShop.getLgt().doubleValue(), storeShop.getLat().doubleValue()) + "");
                storeShopAppDTO.setPhoto(storePhotoDTO);
                storeShopAppDTO.setScore("5");
                shopList.add(storeShopAppDTO);
            }
            long start  = System.currentTimeMillis();
            //排序
            storeSort(shopList);
            System.out.println("排序时间："+(System.currentTimeMillis()-start));
        }

    }

    public void storeSort(List<StoreShopAppDTO> shopList) {
        StoreShopAppDTO storeShopAppDTO;
        for (int i = shopList.size() - 1; i > 0; i--) {
            boolean flag = true;
            for (int j = 0; j < i; j++) {
                double distanceA = Double.parseDouble(shopList.get(j).getDistance());
                double distanceB = Double.parseDouble(shopList.get(j + 1).getDistance());
                if (distanceA > distanceB) {
                    storeShopAppDTO = shopList.get(j);
                    shopList.set(j, shopList.get(j + 1));
                    shopList.set(j + 1, storeShopAppDTO);
                    flag = false;
                }
            }
            if (flag) {
                break;
            }
        }
    }



    private StoreShopAppPageDTO getPagedListbyPage(List<StoreShopAppDTO> data, int pageShow, int page) {
        long startTime = System.currentTimeMillis();
        int dataSize = data.size();
        int pageTotal = Double.valueOf(Math.ceil((double) dataSize / (double) pageShow)).intValue();
        if (page > pageTotal) {
            return new StoreShopAppPageDTO(dataSize, pageTotal, pageShow, new ArrayList<>());
        }
        List<StoreShopAppDTO> pageData = new ArrayList();

        int fromIndex = (page - 1) * pageShow;
        if (fromIndex >= dataSize) {
            return null;
        }
        int toIndex = page * pageShow;
        if (toIndex >= data.size()) {
            toIndex = data.size();
        }
        pageData = data.subList(fromIndex, toIndex);
        System.out.println("处理分页数据时间："+(System.currentTimeMillis()-startTime));
        return new StoreShopAppPageDTO(dataSize, pageTotal, pageShow, pageData);
    }

}
